﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevComponents.DotNetBar;
using System.IO.Ports;
using System.Xml;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace StuMana.UI
{
    public partial class Connect : Office2007Form
    {
        public class Device
        {
            public string _ip;
            public string _hostName;
            public string _macAddress;
            public string _otherInfo;

            public Device()
            {

            }

            public Device(string ip, string hostName, string macAddress, string otherInfo)
            {
                _ip = ip;
                _hostName = hostName;
                _macAddress = macAddress;
                _otherInfo = otherInfo;
            }

            public bool compareDevice(Device dv)
            {
                bool kq = false;
                if (dv._macAddress== this._macAddress)
                    kq = true;
                return kq;
            }

            public void gan(Device dv)
            {
                this._ip = dv._ip;
                this._hostName = dv._hostName;
                this._macAddress = dv._macAddress;
                this._otherInfo = dv._otherInfo;
            }
        }

        List<Device> liDevice = new List<Device>();

        public void ReadDevice()
        {
            liDevice.Clear();
            XmlReader reader = XmlReader.Create("devices.xml");
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element
                && reader.Name == "device")
                {
                    string ip = reader.GetAttribute(0).ToString();
                    string hostName = reader.GetAttribute(1).ToString();
                    string macAddress = reader.GetAttribute(2).ToString();
                    Device dv = new Device(ip, hostName, macAddress, "None");
                    liDevice.Add(dv);                    
                }
            }
            reader.Close();
        }

        public void ResetGridViewDevices()
        {
            for (int i = dgvXListDevices.Rows.Count - 1; i > -1; i--)
            {
                dgvXListDevices.Rows.RemoveAt(i);
            }
        }

        public void LoadListDevice()
        {
            ResetGridViewDevices();
            ReadDevice();
            for (int i = 0; i < liDevice.Count; i++)
            {
                dgvXListDevices.Rows.Add(liDevice[i]._ip, liDevice[i]._hostName, liDevice[i]._macAddress, liDevice[i]._otherInfo);
            }
        }

        public void LoadListDeviceAfter()
        {
            for (int i = 0; i < liDevice.Count; i++)
            {
                dgvXListDevices.Rows.Add(liDevice[i]._ip, liDevice[i]._hostName, liDevice[i]._macAddress, liDevice[i]._otherInfo);              
            }
        }

        public delegate void AsyncCallback(IAsyncResult ar);
        public delegate void AddTolstDiscoveredDevices(object o);

        private UdpState GlobalUDP;

        public Services.COM connect;
        private System.Windows.Forms.Timer readTimer;
        Services.SL025M rfid_reader = new Services.SL025M();

        private int size;
        private byte[] serial_buff = new byte[40];

        /// <summary>
        ///  UDP
        /// </summary>
        struct UdpState
        {
            public System.Net.IPEndPoint EP;
            public System.Net.Sockets.UdpClient UDPClient;
        }

        private bool co = false;
        /// Load setting 
        private Font fontForAll = null;
        private StyleManager managerStyle = new DevComponents.DotNetBar.StyleManager();

        public void ReadSetting()
        {
            XmlReader reader = XmlReader.Create("Settings.xml");
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element
                && reader.Name == "font")
                {
                    string name = reader.GetAttribute(0).ToString();
                    string style = reader.GetAttribute(1).ToString();
                    float size = float.Parse(reader.GetAttribute(2).ToString());
                    if (style == "Bold")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    if (style == "Italic")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    if (style == "Regular")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    if (style == "Strikeout")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Strikeout, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    if (style == "Underline")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));

                    while (reader.NodeType != XmlNodeType.EndElement)
                    {
                        reader.Read();
                        if (reader.Name == "managerstyle" && reader.NodeType == XmlNodeType.Element)
                        {
                            reader.Read();
                            string stylemana = reader.Value.ToString();

                            if (stylemana == "Office2007Blue")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2007Blue;
                            if (stylemana == "Office2007Silver")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2007Silver;
                            if (stylemana == "Office2007Black")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2007Black;
                            if (stylemana == "Windows7Blue")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Windows7Blue;
                            if (stylemana == "Office2007VistaGlass")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2007VistaGlass;
                            if (stylemana == "Office2010Silver")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2010Silver;
                            if (stylemana == "Office2010Blue")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2010Blue;
                            if (stylemana == "Office2010Black")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2010Black;
                        }
                    }
                }
            }
            reader.Close();
        }

        public void ConfigSetting()
        {
            ReadSetting();
            for (int i = 0; i < Controls[0].Controls[2].Controls.Count; i++)
            {
                if (Controls[0].Controls[2].Controls[i] is LabelX)
                {
                    Controls[0].Controls[2].Controls[i].Font = fontForAll;
                }
            }

            styleManager1 = managerStyle;
        }

        /// End Load setting 
        public void AddDiscoveryEntry(object o)
        {
            
        }

        /*--------------------------------------------------------------*/
      
        // timer handler
        private void readTimer_Tick(object sender, EventArgs e)
        {
            rfid_reader.selectCard();
            size = connect.getArray(serial_buff);
            if (size == 5000)
            {
                readTimer.Enabled = false;
                labelItemStatus.Text = "No signal";
            }
            else
            {
                for (int cnt = 0; cnt < size; cnt++)
                {
                   labelItemStatus.Text += Convert.ToString(serial_buff[cnt], 16).PadLeft(2, '0').PadRight(3, ' ').ToUpper();
                }
            }
        }

        private void Connect1_Load(object sender, EventArgs e)
        {
            ConfigSetting();
            LoadListDevice();
            if (dgvXListDevices.Columns.Count > 0)
            {
                int w = dgvXListDevices.Size.Width;
                int widthC = ((int)w /dgvXListDevices.Columns.Count);
                dgvXListDevices.Columns[0].Width = widthC;
                dgvXListDevices.Columns[1].Width = widthC;
                dgvXListDevices.Columns[2].Width = widthC;
                dgvXListDevices.Columns[3].Width = widthC;
            }
            co = true;           
        }

        public Connect()
        {
            InitializeComponent();
            Connect_initial();
        }

        private void Connect_initial()
        {
            string[] s = SerialPort.GetPortNames();
            int i = 0;

            cmbExBaudrate.Items.Clear();
            cmbExBaudrate.Items.Add("1200");
            cmbExBaudrate.Items.Add("2400");
            cmbExBaudrate.Items.Add("4800");
            cmbExBaudrate.Items.Add("9600");
            cmbExBaudrate.Items.Add("19200");
            cmbExBaudrate.Items.Add("38400");
            cmbExBaudrate.Items.Add("57600");
            cmbExBaudrate.Items.Add("115200");
            cmbExBaudrate.Items.Add("230400");
            cmbExBaudrate.SelectedIndex = 4;

            cmbExComPort.Items.Clear();
            foreach (string port in s)
            {
                cmbExComPort.Items.Add(s[i]);
                i++;
            }
            if (cmbExComPort.Items.Count != 0)
                cmbExComPort.SelectedIndex = 0;
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                connect = new Services.COM(cmbExComPort.SelectedItem.ToString(), int.Parse(cmbExBaudrate.SelectedItem.ToString()));
                rfid_reader.get_connect(connect);
                btnConnect.Enabled = false;
                btnDisconnect.Enabled = true;
               labelItemConnect.Text = "COM: " + cmbExComPort.SelectedItem.ToString();
               foreach (Form frm in Application.OpenForms)
               {
                   if (frm is Login)
                   {
                       Login frmTemp = (Login)frm;
                       frmTemp.rfid_reader = rfid_reader;
                       frmTemp.connect = connect;
                   }
               }                                            
            }
            catch (Exception es)
            {
               // ts_connect.Text = "COM Error: " + es.Message;
                labelItemConnect.Text = "COM Error: " + es.Message;
            }        
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {           
            try
            {
                if (!btnConnect.Enabled)
                    connect.closeCOMPort();
                // button connect disable
                btnConnect.Enabled = true;
                //button disconnect
                btnDisconnect.Enabled = false;             
                labelItemStatus.Text = "None";
                labelItemConnect.Text = "|None";
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "COM Error");
            }       
        }

        private void Connect1_FormClosed(object sender, FormClosedEventArgs e)
        {
            Environment.Exit(Environment.ExitCode);
            Application.ExitThread();
            Application.Exit();
        }

        private void Connect1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Environment.Exit(Environment.ExitCode);
            Application.ExitThread();
            Application.Exit();
        }

        private void Connect1_Resize(object sender, EventArgs e)
        {
            if (dgvXListDevices.Columns.Count>0)// (co == true)
            {
                int w = dgvXListDevices.Size.Width;
                int widthC = ((int)w / dgvXListDevices.Columns.Count);
                dgvXListDevices.Columns[0].Width = widthC;
                dgvXListDevices.Columns[1].Width = widthC;
                dgvXListDevices.Columns[2].Width = widthC;
                dgvXListDevices.Columns[3].Width = widthC;
            }
        }

        private void lvExDevice_ItemActivate(object sender, EventArgs e)
        {
           
        }

        class packetDevice
        {
            public byte[] _data;
            public string _ip;

            public packetDevice()
            {
                _data = new byte[1024];
                _ip = "";
            }

            public packetDevice(byte[] data, string ip)
            {
                _data = data;
                _ip = ip;
            }

        }

        List<packetDevice> liPacketUDP = new List<packetDevice>();
        /// <summary>
        /// Thread Receive 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        
        public void ReceivePacket()
        {    
            if (btnDiscover.Text == "Stop")
            {
                while (true)
                {
                    IPEndPoint ep;
                    try
                    {
                        ep = new IPEndPoint(0, 30303);
                        byte[] receiveData = GlobalUDP.UDPClient.Receive(ref ep);
                        if (receiveData.Length > 0)
                        {
                            packetDevice packet = new packetDevice(receiveData, ep.Address.ToString());
                            liPacketUDP.Add(packet);
                        }
                    }
                    catch (Exception e)
                    {
                       // GlobalUDP.UDPClient.Close();
                    }
                    Thread.Sleep(10);
                }
            }
        }

        Thread thReceive;

        public int CheckIndexInListDevice(Device dv)
        {
            int index = -1;
            for (int i = 0; i < liDevice.Count; i++)
            {
                if (liDevice[i].compareDevice(dv))
                {
                    index = i;
                    return index;
                }
            }
            return index;
        }

        public void ReloadListDevice()
        {
            for (int i = 0; i < liPacketUDP.Count; i++)
            {
                packetDevice packet = new packetDevice();
                packet = liPacketUDP.ElementAt(i);
                string ReceiveString = Encoding.ASCII.GetString(packet._data);
                string[] str = ReceiveString.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
               // MessageBox.Show(str[1].ToString() + "aa");
                if (str.Length > 2)
                {
                    // str[0] = "WFRFID" str[1] = mac  str[2] = otherinfo
                    Device dv = new Device(packet._ip, str[0] + str[2], str[1], "Active");

                    int index = CheckIndexInListDevice(dv);

                    if (index > -1)
                    {
                        liDevice[index]._otherInfo = "Active";
                    }
                    else
                    {
                        liDevice.Add(dv);
                    }
                }
                
            }
            liPacketUDP = new List<packetDevice>();
            LoadListDeviceAfter();
        }

        public void SaveListDevice()
        {
            // Write setting 
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;

            XmlWriter writer = XmlWriter.Create("devices.xml", settings);
            writer.WriteStartDocument();
            writer.WriteComment("setting file for all form");
            writer.WriteStartElement("devices");

            for (int i = 0; i < liDevice.Count; i++)
            {
                writer.WriteStartElement("device");
                writer.WriteAttributeString("ip", liDevice[i]._ip.ToString());
                writer.WriteAttributeString("hostname", liDevice[i]._hostName.ToString());
                writer.WriteAttributeString("macaddress", liDevice[i]._macAddress.ToString());
                writer.WriteEndElement();
            }
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
            
        }
        private void btnDiscover_Click(object sender, EventArgs e)
        {
            if (btnDiscover.Text == "Discovery Device")
            {
                try
                {
                    // Clear the listbox of all current discovery responses
                    ResetGridViewDevices();  
                 
                    // Try to send the discovery request message
                    byte[] DiscoverMsg = Encoding.ASCII.GetBytes("Discovery: Who is out there?");
                    GlobalUDP.UDPClient = new UdpClient();
                    GlobalUDP.UDPClient.EnableBroadcast = true;
                    GlobalUDP.UDPClient.MulticastLoopback = false;
                    GlobalUDP.EP = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("255.255.255.255"), 30303);
                    
                    System.Net.IPEndPoint BindEP = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 30303);

                    GlobalUDP.UDPClient.Client.Bind(BindEP);

                    GlobalUDP.UDPClient.Send(DiscoverMsg, DiscoverMsg.Length, GlobalUDP.EP);
                    // Enable the transmission of broadcast packets without having them be received by ourself

                    // Configure ourself to receive discovery responses
                    
                    //// broadcast discovery 
                    thReceive = new Thread(new ThreadStart(ReceivePacket));

                    //thread nhận tin bắt đầu 
                    thReceive.Start();
                    //  thread process bắt đầu

                    // Transmit the discovery request message
                    labelItemStatus.Text = "Discovery...";
                    btnDiscover.Text = "Stop";
                }
                catch
                {
                    MessageBox.Show("Unable to transmit discovery message.  Check network connectivity and ensure that no other instances of this program are running.", "Error", MessageBoxButtons.OK);
                    return;
                }

            }
            else
            {
                GlobalUDP.UDPClient.Close();
                thReceive.Abort();
                btnDiscover.Text = "Discovery Device";
                labelItemStatus.Text = "None";

                ReloadListDevice();
                SaveListDevice();

            }
        }

    }
}
